Ръководство за обединяване на DataFrames в Python Pandas. Включва вътрешно, външно, ляво и дясно свързване с примери за ефективен анализ на данни.
Обединяване в Python Pandas: Овладяване на стратегии за свързване на DataFrame за анализ на данни
Манипулацията на данни е решаващ аспект в анализа на данни, а библиотеката Pandas в Python предоставя мощни инструменти за тази цел. Сред тези инструменти, обединяването и свързването на DataFrames са основни операции за комбиниране на набори от данни въз основа на общи колони или индекси. Това изчерпателно ръководство изследва различни стратегии за свързване на DataFrame в Pandas, като ви дава знанията за ефективно комбиниране и анализ на данни от различни източници.
Разбиране на обединяването и свързването на DataFrame
Обединяването и свързването на DataFrames включва комбинирането на два или повече DataFrames в един единствен DataFrame въз основа на споделена колона или индекс. Основната разлика между `merge` и `join` е, че `merge` е функция на библиотеката Pandas и обикновено свързва DataFrames по колони, докато `join` е метод на DataFrame, който свързва DataFrames предимно по индекси, въпреки че може да се използва и с колони.
Ключови концепции
- DataFrames: Двуизмерни етикетирани структури от данни с колони от потенциално различни типове.
- Общи колони/индекси: Колони или индекси, които споделят едно и също име и тип данни между DataFrames, служещи като основа за обединяване/свързване.
- Типове свързване: Различни стратегии за обработка на несъответстващи редове по време на процеса на обединяване/свързване, включително вътрешни, външни, леви и десни свързвания.
Обединяване на DataFrame с `pd.merge()`
Функцията `pd.merge()` е основният инструмент за обединяване на DataFrames въз основа на колони. Тя предлага гъвкав начин за комбиниране на данни въз основа на една или повече общи колони.
Синтаксис
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
Параметри
- left: Левият DataFrame за обединяване.
- right: Десният DataFrame за обединяване.
- how: Типът обединяване, което да се извърши ('inner', 'outer', 'left', 'right'). По подразбиране е 'inner'.
- on: Името на колоната(ите), по която да се свърже. Те трябва да се намират и в двата DataFrame.
- left_on: Името на колоната(ите) в левия DataFrame, която да се използва като ключ(ове) за свързване.
- right_on: Името на колоната(ите) в десния DataFrame, която да се използва като ключ(ове) за свързване.
- left_index: Ако е True, използвайте индекса от левия DataFrame като ключ(ове) за свързване.
- right_index: Ако е True, използвайте индекса от десния DataFrame като ключ(ове) за свързване.
- sort: Сортирайте получения DataFrame лексикографски по ключовете за свързване. По подразбиране е False.
- suffixes: Кортеж от стрингови наставки, които да се приложат към припокриващи се имена на колони. По подразбиране е ('_x', '_y').
- copy: Ако е False, избягвайте копирането на данни в новия DataFrame, когато е възможно. По подразбиране е True.
- indicator: Ако е True, добавя колона, наречена '_merge', която указва източника на всеки ред.
- validate: Проверява дали обединяването е от посочения тип. "one_to_one", "one_to_many", "many_to_one", "many_to_many".
Обяснение на типовете свързване
Параметърът `how` във `pd.merge()` определя типа на извършеното свързване. Различните типове свързване обработват несъответстващите редове по различни начини.
Вътрешно свързване (Inner Join)
Вътрешното свързване връща само редовете, които имат съвпадащи стойности и в двата DataFrame въз основа на ключовете за свързване. Редовете с несъвпадащи стойности се изключват от резултата.
Пример:
Разгледайте два DataFrames:
import pandas as pd
# DataFrame 1: Customer Orders
df_orders = pd.DataFrame({
'order_id': [1, 2, 3, 4, 5],
'customer_id': [101, 102, 103, 104, 105],
'product_id': [1, 2, 1, 3, 2],
'quantity': [2, 1, 3, 1, 2]
})
# DataFrame 2: Customer Information
df_customers = pd.DataFrame({
'customer_id': [101, 102, 103, 106],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David'],
'country': ['USA', 'Canada', 'UK', 'Australia']
})
# Inner Join
df_inner = pd.merge(df_orders, df_customers, on='customer_id', how='inner')
print(df_inner)
Изход:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
В този пример, вътрешното свързване комбинира DataFrames `df_orders` и `df_customers` въз основа на колоната `customer_id`. В резултата са включени само клиенти, които са направили поръчки. Клиентът 'David' (customer_id 106) е изключен, защото няма поръчки.
Външно свързване (Full Outer Join)
Външното свързване връща всички редове от двата DataFrame, включително несъответстващи редове. Ако даден ред няма съвпадение в другия DataFrame, съответните колони ще съдържат `NaN` (Not a Number) стойности.
Пример:
# Outer Join
df_outer = pd.merge(df_orders, df_customers, on='customer_id', how='outer')
print(df_outer)
Изход:
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 4.0 104 3.0 1.0 NaN NaN
4 5.0 105 2.0 2.0 NaN NaN
5 NaN 106 NaN NaN David Australia
Външното свързване включва всички клиенти и всички поръчки. Клиенти 104 и 105 имат поръчки, но нямат информация за клиенти, а клиент 106 има информация за клиенти, но няма поръчки. Липсващите стойности са представени като `NaN`.
Ляво свързване (Left Join)
Лявото свързване връща всички редове от левия DataFrame и съвпадащите редове от десния DataFrame. Ако даден ред в левия DataFrame няма съвпадение в десния DataFrame, съответните колони от десния DataFrame ще съдържат `NaN` стойности.
Пример:
# Left Join
df_left = pd.merge(df_orders, df_customers, on='customer_id', how='left')
print(df_left)
Изход:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
Лявото свързване включва всички поръчки от `df_orders`. Клиенти 104 и 105 имат поръчки, но нямат информация за клиенти, така че колоните `customer_name` и `country` са `NaN` за тези поръчки.
Дясно свързване (Right Join)
Дясното свързване връща всички редове от десния DataFrame и съвпадащите редове от левия DataFrame. Ако даден ред в десния DataFrame няма съвпадение в левия DataFrame, съответните колони от левия DataFrame ще съдържат `NaN` стойности.
Пример:
# Right Join
df_right = pd.merge(df_orders, df_customers, on='customer_id', how='right')
print(df_right)
Изход:
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 NaN 106 NaN NaN David Australia
Дясното свързване включва всички клиенти от `df_customers`. Клиент 106 има информация за клиенти, но няма поръчки, така че колоните `order_id`, `product_id` и `quantity` са `NaN` за този клиент.
Свързване на DataFrame с `df.join()`
Методът `df.join()` се използва предимно за свързване на DataFrames въз основа на техните индекси. Може да се използва и за свързване по колони, но обикновено е по-удобно да се използва `pd.merge()` за свързвания, базирани на колони.
Синтаксис
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
Параметри
- other: Другият DataFrame за свързване.
- on: Име на колона за свързване. Трябва да се подаде, ако индексът не се използва като ключ за свързване.
- how: Как да се обработи операцията на левия и десния набор. По подразбиране е 'left'.
- lsuffix: Наставка, която да се използва от левия DataFrame за припокриващи се имена на колони.
- rsuffix: Наставка, която да се използва от десния DataFrame за припокриващи се имена на колони.
- sort: Сортирайте получения DataFrame лексикографски по ключовете за свързване. По подразбиране е False.
Свързване по индекс
При свързване по индекс параметърът `on` не се използва.
Пример:
# DataFrame 1: Customer Orders with Customer ID as Index
df_orders_index = df_orders.set_index('customer_id')
# DataFrame 2: Customer Information with Customer ID as Index
df_customers_index = df_customers.set_index('customer_id')
# Join on Index (Left Join)
df_join_index = df_orders_index.join(df_customers_index, how='left')
print(df_join_index)
Изход:
order_id product_id quantity customer_name country
customer_id
101 1 1 2 Alice USA
102 2 2 1 Bob Canada
103 3 1 3 Charlie UK
104 4 3 1 NaN NaN
105 5 2 2 NaN NaN
В този пример методът `join()` се използва за извършване на ляво свързване по индекса (`customer_id`). Резултатът е подобен на лявото свързване с помощта на `pd.merge()`, но свързването е базирано на индекса, а не на колона.
Свързване по колона
За да се свърже по колона с помощта на `df.join()`, трябва да се укаже параметърът `on`.
Пример:
# Joining on a column
df_join_column = df_orders.join(df_customers.set_index('customer_id'), on='customer_id', how='left')
print(df_join_column)
Изход:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
Този пример демонстрира свързване на `df_orders` с `df_customers` с помощта на колоната `customer_id`. Имайте предвид, че `customer_id` е зададен като индекс в `df_customers` преди извършване на свързването.
Обработка на припокриващи се колони
При обединяване или свързване на DataFrames е обичайно да се срещат припокриващи се имена на колони (колони с едно и също име в двата DataFrame). Pandas предоставя параметъра `suffixes` във `pd.merge()` и параметрите `lsuffix` и `rsuffix` във `df.join()` за справяне с тези ситуации.
Използване на `suffixes` във `pd.merge()`
Параметърът `suffixes` ви позволява да укажете наставки, които ще бъдат добавени към припокриващите се имена на колони, за да ги разграничите.
Пример:
# DataFrame 1: Product Information
df_products1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C'],
'price': [10, 20, 15]
})
# DataFrame 2: Product Information (with potentially updated prices)
df_products2 = pd.DataFrame({
'product_id': [1, 2, 4],
'product_name': ['Product A', 'Product B', 'Product D'],
'price': [12, 18, 25]
})
# Merge with suffixes
df_merged_suffixes = pd.merge(df_products1, df_products2, on='product_id', suffixes=('_old', '_new'))
print(df_merged_suffixes)
Изход:
product_id product_name_old price_old product_name_new price_new
0 1 Product A 10 Product A 12
1 2 Product B 20 Product B 18
В този пример колоните `product_name` и `price` присъстват и в двата DataFrame. Параметърът `suffixes` добавя наставките `_old` и `_new`, за да разграничи колоните съответно от левия и десния DataFrame.
Използване на `lsuffix` и `rsuffix` във `df.join()`
Параметрите `lsuffix` и `rsuffix` предоставят подобна функционалност за `df.join()`. `lsuffix` добавя към припокриващите се колони на левия DataFrame, а `rsuffix` към тези на десния DataFrame.
Пример:
# Join with lsuffix and rsuffix
df_products1_index = df_products1.set_index('product_id')
df_products2_index = df_products2.set_index('product_id')
df_joined_suffixes = df_products1_index.join(df_products2_index, lsuffix='_old', rsuffix='_new', how='outer')
print(df_joined_suffixes)
Изход:
product_name_old price_old product_name_new price_new
product_id
1 Product A 10.0 Product A 12.0
2 Product B 20.0 Product B 18.0
3 Product C 15.0 NaN NaN
4 NaN NaN Product D 25.0
Практически примери и случаи на употреба
Обединяването и свързването на DataFrames са широко използвани в различни сценарии за анализ на данни. Ето някои практически примери:
Комбиниране на данни за продажби с информация за продукти
Често срещан случай на употреба е комбинирането на данни за продажби с информация за продукти. Да предположим, че имате DataFrame, съдържащ транзакции за продажби, и друг DataFrame, съдържащ детайли за продукти. Можете да обедините тези DataFrames, за да обогатите данните за продажби с продуктова информация.
Пример:
# Sales Transactions Data
df_sales = pd.DataFrame({
'transaction_id': [1, 2, 3, 4, 5],
'product_id': [101, 102, 103, 101, 104],
'quantity': [2, 1, 3, 1, 2],
'sales_date': ['2023-01-15', '2023-02-20', '2023-03-10', '2023-04-05', '2023-05-01']
})
# Product Information Data
df_products = pd.DataFrame({
'product_id': [101, 102, 103, 104],
'product_name': ['Laptop', 'Mouse', 'Keyboard', 'Monitor'],
'category': ['Electronics', 'Electronics', 'Electronics', 'Electronics'],
'price': [1200, 25, 75, 300]
})
# Merge Sales Data with Product Information
df_sales_enriched = pd.merge(df_sales, df_products, on='product_id', how='left')
print(df_sales_enriched)
Изход:
transaction_id product_id quantity sales_date product_name category price
0 1 101 2 2023-01-15 Laptop Electronics 1200
1 2 102 1 2023-02-20 Mouse Electronics 25
2 3 103 3 2023-03-10 Keyboard Electronics 75
3 4 101 1 2023-04-05 Laptop Electronics 1200
4 5 104 2 2023-05-01 Monitor Electronics 300
Полученият DataFrame `df_sales_enriched` съдържа транзакциите за продажби заедно със съответната продуктова информация, което позволява по-подробен анализ на тенденциите в продажбите и производителността на продуктите.
Комбиниране на клиентски данни с демографска информация
Друг често срещан случай на употреба е комбинирането на клиентски данни с демографска информация. Това позволява анализ на поведението на клиентите въз основа на демографски фактори.
Пример:
# Customer Data
df_customers = pd.DataFrame({
'customer_id': [1, 2, 3, 4, 5],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin']
})
# Demographic Information Data
df_demographics = pd.DataFrame({
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin'],
'population': [8419000, 8982000, 13960000, 5312000, 3769000],
'average_income': [75000, 65000, 85000, 90000, 55000]
})
# Merge Customer Data with Demographic Information
df_customer_demographics = pd.merge(df_customers, df_demographics, on='city', how='left')
print(df_customer_demographics)
Изход:
customer_id customer_name city population average_income
0 1 Alice New York 8419000 75000
1 2 Bob London 8982000 65000
2 3 Charlie Tokyo 13960000 85000
3 4 David Sydney 5312000 90000
4 5 Eve Berlin 3769000 55000
Полученият DataFrame `df_customer_demographics` съдържа клиентски данни заедно с демографската информация за съответните им градове, което позволява анализ на поведението на клиентите въз основа на градската демография.
Анализиране на данни от глобалната верига на доставки
Обединяването в Pandas е ценно за анализиране на данни от глобалната верига на доставки, където информацията често е разпръсната в множество таблици. Например, свързването на данни за доставчици, информация за доставка и данни за продажби може да разкрие тесни места и да оптимизира логистиката.
Пример:
# Supplier Data
df_suppliers = pd.DataFrame({
'supplier_id': [1, 2, 3],
'supplier_name': ['GlobalTech', 'EuroParts', 'AsiaSource'],
'location': ['Taiwan', 'Germany', 'China']
})
# Shipping Data
df_shipments = pd.DataFrame({
'shipment_id': [101, 102, 103, 104],
'supplier_id': [1, 2, 3, 1],
'destination': ['USA', 'Canada', 'Australia', 'Japan'],
'shipment_date': ['2023-01-10', '2023-02-15', '2023-03-20', '2023-04-25']
})
# Merge Supplier and Shipment Data
df_supply_chain = pd.merge(df_shipments, df_suppliers, on='supplier_id', how='left')
print(df_supply_chain)
Изход:
shipment_id supplier_id destination shipment_date supplier_name location
0 101 1 USA 2023-01-10 GlobalTech Taiwan
1 102 2 Canada 2023-02-15 EuroParts Germany
2 103 3 Australia 2023-03-20 AsiaSource China
3 104 1 Japan 2023-04-25 GlobalTech Taiwan
Разширени техники за обединяване
Обединяване по множество колони
Можете да обединявате DataFrames въз основа на множество колони, като подадете списък с имена на колони на параметъра `on`.
Пример:
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'quantity': [10, 15, 20, 25]
})
# DataFrame 2
df2 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'price': [5, 7, 8, 10]
})
# Merge on multiple columns
df_merged_multiple = pd.merge(df1, df2, on=['product_id', 'color'], how='inner')
print(df_merged_multiple)
Изход:
product_id color quantity price
0 1 red 10 5
1 1 blue 15 7
2 2 red 20 8
3 2 blue 25 10
Обединяване с различни имена на колони
Ако колоните за свързване имат различни имена в двата DataFrame, можете да използвате параметрите `left_on` и `right_on`, за да укажете имената на колоните, които да се използват за обединяване.
Пример:
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C']
})
# DataFrame 2
df2 = pd.DataFrame({
'id': [1, 2, 4],
'price': [10, 20, 25]
})
# Merge with different column names
df_merged_different = pd.merge(df1, df2, left_on='product_id', right_on='id', how='left')
print(df_merged_different)
Изход:
product_id product_name id price
0 1 Product A 1.0 10.0
1 2 Product B 2.0 20.0
2 3 Product C NaN NaN
Използване на `indicator` за анализ на обединяването
Параметърът `indicator` във `pd.merge()` добавя колона на име `_merge` към получения DataFrame, указваща източника на всеки ред. Това е полезно за разбиране кои редове са съвпаднали и кои не.
Пример:
# Merge with indicator
df_merged_indicator = pd.merge(df_orders, df_customers, on='customer_id', how='outer', indicator=True)
print(df_merged_indicator)
Изход:
order_id customer_id product_id quantity customer_name country _merge
0 1.0 101 1.0 2.0 Alice USA both
1 2.0 102 2.0 1.0 Bob Canada both
2 3.0 103 1.0 3.0 Charlie UK both
3 4.0 104 3.0 1.0 NaN NaN left_only
4 5.0 105 2.0 2.0 NaN NaN left_only
5 NaN 106 NaN NaN David Australia right_only
Колоната `_merge` указва дали редът е от двата DataFrame (`both`), само от левия DataFrame (`left_only`) или само от десния DataFrame (`right_only`).
Валидиране на типове обединяване
Параметърът `validate` гарантира, че операцията по обединяване е в съответствие с очакваните типове взаимоотношения между DataFrames (напр. 'one_to_one', 'one_to_many'). Това помага за предотвратяване на несъответствия и грешки в данните.
Пример:
# Example with one-to-one validation
df_users = pd.DataFrame({
'user_id': [1, 2, 3],
'username': ['john_doe', 'jane_smith', 'peter_jones']
})
df_profiles = pd.DataFrame({
'user_id': [1, 2, 3],
'profile_description': ['Software Engineer', 'Data Scientist', 'Project Manager']
})
# Performing a one-to-one merge with validation
merged_df = pd.merge(df_users, df_profiles, on='user_id', validate='one_to_one')
print(merged_df)
Ако обединяването нарушава указаната валидация (напр. връзка "много към едно", когато е посочена "едно към едно"), ще бъде повдигната `MergeError`, което ще ви предупреди за потенциални проблеми с целостта на данните.
Съображения за производителност
Обединяването и свързването на DataFrames може да бъде изчислително скъпо, особено за големи набори от данни. Ето няколко съвета за подобряване на производителността:
- Използвайте подходящия тип свързване: Изборът на правилния тип свързване може значително да повлияе на производителността. Например, ако имате нужда само от съвпадащи редове, използвайте вътрешно свързване.
- Индексирайте колоните за свързване: Индексирането на колоните за свързване може да ускори процеса на обединяване.
- Използвайте подходящи типове данни: Уверете се, че колоните за свързване имат съвместими типове данни.
- Избягвайте ненужни копия: Задайте `copy=False` във `pd.merge()` и `df.join()`, за да избегнете създаването на ненужни копия на данните.
Заключение
Обединяването и свързването на DataFrames са основни операции в анализа на данни. Като разбирате различните типове свързване и техники, можете ефективно да комбинирате и анализирате данни от различни източници, отключвайки ценни прозрения и вземайки информирани решения. От комбинирането на данни за продажби с информация за продукти до анализирането на глобалните вериги за доставки, овладяването на тези техники ще ви даде възможност да се справяте със сложни задачи за манипулиране на данни с увереност. Не забравяйте да вземете предвид последиците за производителността, когато работите с големи набори от данни, и да използвате разширени функции като параметрите `indicator` и `validate` за по-стабилен и проницателен анализ.